/**
 *
 * \file CWindow.cpp
 * \brief This file contains the CWindow class implementation.
 * \author Vladimir Klubkov (aka marked)
 *
 * Last changes date:
 * \date 15.03.2011
 *
 * Copyright 2011 Vladimir Klubkov <marked-one@yandex.ru>
 *
 * This file is part of OOXlib.
 *
 * OOXLib is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * OOXlib is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with OOXlib; if not, you can try to find  it here:
 * http://www.gnu.org/licenses/gpl.txt
 * or write to the Free Software Foundation, Inc., 59 Temple Place,
 * Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include "../include/CWindow.h"

namespace OOXlib {

/**
 * Constructor. Calls the base-class constructor.
 * \param File Source code file name.
 * \param iLine Source code line.
 * \param Function Function name.
 */
CWindow::CNULLPtrIWindowException::CNULLPtrIWindowException(const ::std::string &File, const int iLine, const ::std::string &Function)
: CException(File, iLine, Function, "NULL pointer was specified as the IWindow object pointer.") {}
/**
 * Constructor. Calls the base-class constructor.
 * \param File Source code file name.
 * \param iLine Source code line.
 * \param Function Function name.
 */
CWindow::CXStringListToTextPropertyException::CXStringListToTextPropertyException(const ::std::string &File, const int iLine, const ::std::string &Function)
: CException(File, iLine, Function, "Failed to create window and icon names text properties. XStringListToTextProperty function falied.") {}
/**
 * Constructor. Calls the base-class constructor.
 * \param File Source code file name.
 * \param iLine Source code line.
 * \param Function Function name.
 */
CWindow::CXGetVisualInfoException::CXGetVisualInfoException(const ::std::string &File, const int iLine, const ::std::string &Function)
: CException(File, iLine, Function, "No visual info found. XGetVisualInfo function falied.") {}
/**
 * Constructor.
 * \param pXServerConnection A pointer to the CXServerConnection object.
 * \param pScreen Pointer to the CScreen object.
 */
CWindow::CWindow(const CXServerConnection *pXServerConnection, const CScreen *pScreen)
: m_pXServerConnection(pXServerConnection), m_pScreen(pScreen), m_pEventHandler(NULL), m_pIcon(NULL), m_bHasParent(false), m_bShowCursor(false), m_iEventMask(NoEventMask), m_pParentWindow(NULL), m_iId(0) {
    if(NULL == m_pXServerConnection) {
        OOXLib_THROW(CNULLPtrConnectionException);
    }
    if(NULL == m_pScreen) {
        OOXLib_THROW(CNULLPtrScreenException);
    }
    CUInt2dRectangle rectangle(0u, 0u, 256u, 256u);
    ::std::string empty;
    Create(pScreen, NULL, rectangle, NULL, NULL, m_iEventMask, NULL, empty, empty, empty, NULL, 0u, 0u, true, true);
}
/**
 * Constructor.
 * \param pXServerConnection A pointer to the CXServerConnection object.
 * \param pScreen Pointer to the CScreen object.
 * \param pEventHandler Pointer to the CEventHandler object.
 * \param Rectangle Window rectangle (contains coordinates of the left-top corner, width and height).
 * \param iEventMask Eevent mask, tells the window manager, which events must be sent to this window.
 * \param WindowName Window name, will be displayed in the iconic state and on the title bar of the window.
 */
CWindow::CWindow(const CXServerConnection *pXServerConnection, const CScreen *pScreen, const CUInt2dRectangle &Rectangle, const unsigned int iEventMask,
                 const IEventHandler *pEventHandler, const ::std::string &WindowName)
: m_pXServerConnection(pXServerConnection), m_pScreen(pScreen), m_pEventHandler(NULL), m_pIcon(NULL), m_bHasParent(false), m_bShowCursor(false), m_iEventMask(NoEventMask), m_pParentWindow(NULL), m_iId(0) {
    if(NULL == m_pXServerConnection) {
        OOXLib_THROW(CNULLPtrConnectionException);
    }
    if(NULL == m_pScreen) {
        OOXLib_THROW(CNULLPtrScreenException);
    }
    ::std::string empty;
    Create(pScreen, NULL, Rectangle, NULL, NULL, iEventMask, pEventHandler, WindowName, empty, empty, NULL, 0u, 0u, true, true);
}
/**
 * Constructor.
 * \param pXServerConnection A pointer to the CXServerConnection object.
 * \param pScreen Pointer to the CScreen object.
 * \param pEventHandler Pointer to the CEventHandler object.
 * \param pParentWindow Pointer to the parent window object.
 * \param Rectangle Window rectangle (contains coordinates of the left-top corner, width and height).
 * \param pMinSize Minimal window size.
 * \param pMaxSize Maximal window size.
 * \param iEventMask Eevent mask, tells the window manager, which events must be sent to this window.
 * \param WindowName Window name, will be displayed in the iconic state and on the title bar of the window.
 * \param IconPath Path to the icon pixmap file.
 * \param pBackgroundColor Background color of the window.
 * \param iDepth Window depth.
 * \param iBorderWidth Window border width.
 * \param bIsResizeable If true, the window will be resizable, if false - not.
 */
CWindow::CWindow(const CXServerConnection *pXServerConnection, const CScreen *pScreen, IWindow *pParentWindow, const CUInt2dRectangle &Rectangle,
                 const CUInt2dSize *pMinSize, const CUInt2dSize *pMaxSize, const unsigned int iEventMask, const IEventHandler *pEventHandler,
                 const ::std::string &WindowName, const ::std::string &IconPath, const CColor *pBackgroundColor, const unsigned int iDepth,
                 const unsigned int iBorderWidth, const bool bIsResizeable)
: m_pXServerConnection(pXServerConnection), m_pScreen(pScreen), m_pEventHandler(NULL), m_pIcon(NULL), m_bHasParent(false), m_bShowCursor(false), m_iEventMask(NoEventMask), m_pParentWindow(NULL), m_iId(0) {
    if(NULL == m_pXServerConnection) {
        OOXLib_THROW(CNULLPtrConnectionException);
    }
    if(NULL == m_pScreen) {
        OOXLib_THROW(CNULLPtrScreenException);
    }
    ::std::string empty;
    Create(pScreen, pParentWindow, Rectangle, pMinSize, pMaxSize, iEventMask, pEventHandler, WindowName, empty, IconPath, pBackgroundColor, iDepth, iBorderWidth, bIsResizeable, true);
}
/**
 * Constructor.
 * \param pXServerConnection A pointer to the CXServerConnection object.
 * \param pScreen Pointer to the CScreen object.
 * \param pEventHandler Pointer to the CEventHandler object.
 * \param pParentWindow Pointer to the parent window object.
 * \param Rectangle Window rectangle (contains coordinates of the left-top corner, width and height).
 * \param pMinSize Minimal window size.
 * \param pMaxSize Maximal window size.
 * \param iEventMask Eevent mask, tells the window manager, which events must be sent to this window.
 * \param WindowName Window name, will be displayed in the iconic state and on the title bar of the window.
 * \param ClassName Window class name.
 * \param IconPath Path to the icon pixmap file.
 * \param pBackgroundColor Background color of the window.
 * \param iDepth Window depth.
 * \param iBorderWidth Window border width.
 * \param bIsResizeable If true, the window will be resizable, if false - not.
 * \param bShowCursor If true, the system cursor will be shown, else - hidden.
 */
CWindow::CWindow(const CXServerConnection *pXServerConnection, const CScreen *pScreen, IWindow *pParentWindow, const CUInt2dRectangle &Rectangle,
                 const CUInt2dSize *pMinSize, const CUInt2dSize *pMaxSize, const unsigned int iEventMask, const IEventHandler *pEventHandler,
                 const ::std::string &WindowName, const ::std::string &ClassName, const ::std::string &IconPath, const CColor *pBackgroundColor,
                 const unsigned int iDepth, const unsigned int iBorderWidth, const bool bIsResizeable, const bool bShowCursor)
: m_pXServerConnection(pXServerConnection), m_pScreen(pScreen), m_pEventHandler(NULL), m_pIcon(NULL), m_bHasParent(false), m_bShowCursor(false), m_iEventMask(NoEventMask), m_pParentWindow(NULL), m_iId(0) {
    if(NULL == m_pXServerConnection) {
        OOXLib_THROW(CNULLPtrConnectionException);
    }
    if(NULL == m_pScreen) {
        OOXLib_THROW(CNULLPtrScreenException);
    }
    Create(pScreen, pParentWindow, Rectangle, pMinSize, pMaxSize, iEventMask, pEventHandler, WindowName, ClassName, IconPath, pBackgroundColor, iDepth, iBorderWidth, bIsResizeable, bShowCursor);
}
/**
 * Destructor.
 */
CWindow::~CWindow() {
    Destroy();
}
/**
 * Creates the window.
 * \param pScreen Pointer to the CScreen object.
 * \param pParentWindow Pointer to the parent window object.
 * \param pEventHandler Pointer to the CEventHandler object.
 * \param Rectangle Window rectangle (contains coordinates of the left-top corner, width and height).
 * \param pMinSize Minimal window size.
 * \param pMaxSize Maximal window size.
 * \param iEventMask Eevent mask, tells the window manager, which events must be sent to this window.
 * \param WindowName Window name, will be displayed in the iconic state and on the title bar of the window.
 * \param ClassName Window class name.
 * \param IconPath Path to the icon pixmap file.
 * \param pBackgroundColor Background color of the window.
 * \param iDepth Window depth.
 * \param iBorderWidth Window border width.
 * \param bIsResizeable If true, the window will be resizable, if false - not.
 * \param bShowCursor If true, the system cursor will be shown, else - hidden.
 */
void CWindow::Create(const CScreen *pScreen,IWindow *pParentWindow, const CUInt2dRectangle &Rectangle, const CUInt2dSize *pMinSize, const CUInt2dSize *pMaxSize,
                     const unsigned int iEventMask, const IEventHandler *pEventHandler, const ::std::string &WindowName, const ::std::string &ClassName,
                     const ::std::string &IconPath, const CColor *pBackgroundColor,  const unsigned int iDepth, const unsigned int iBorderWidth,
                     const bool bIsResizeable, const bool bShowCursor) {
    // If window's parent is the root window, set the default window position to (0,0).
    // That's because the (0,0) values doesn't take any effect.
    unsigned int posX = 0u;
    unsigned int posY = 0;
    if(NULL != pParentWindow) {
        posX = Rectangle.GetPositionX();
        posY = Rectangle.GetPositionY();
    }
     // Create the visual info template - what we want to become in our visual.
    ::XVisualInfo visualInfoTemplate;
    visualInfoTemplate.screen = pScreen->Get();
    visualInfoTemplate.depth = iDepth;
    // Find the visual info, which has attributes equal to the attributes specified by the template.
    ::XVisualInfo* visualInfo;
    int numberOfStructuresFound;
    visualInfo = ::XGetVisualInfo(m_pXServerConnection->Get(), VisualScreenMask, &visualInfoTemplate, &numberOfStructuresFound);
    if(NULL == visualInfo) {
        OOXLib_THROW(CXGetVisualInfoException);
    }
    // Create a colormap for this visual.
    // XCreateColormap can generate BadAlloc, BadMatch, BadValue, and BadWindow errors.
    ::Colormap colorMap = ::XCreateColormap(m_pXServerConnection->Get(), ::XRootWindow(m_pXServerConnection->Get(), visualInfo->screen), visualInfo->visual, AllocNone);
    // Get border's and background's pixels.
    unsigned long borderPixel = ::XBlackPixel(m_pXServerConnection->Get(), pScreen->Get());
    unsigned long backgroundPixel = ::XWhitePixel(m_pXServerConnection->Get(), pScreen->Get());
    if(NULL != pBackgroundColor) {
        backgroundPixel = pBackgroundColor->GetPixel();
    }
    // Set window attributes.
    ::XSetWindowAttributes setWindowAttributes;
    setWindowAttributes.colormap            = colorMap;
    setWindowAttributes.border_pixel        = borderPixel;
    setWindowAttributes.background_pixel    = backgroundPixel;
    setWindowAttributes.event_mask          = iEventMask;
    // Attributes mask.
    unsigned long valueMask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
    // If cursor must be hidden - create the transparent cursor.
    ::Pixmap cursorPixmap;
    ::Cursor cursorId;
    if(!bShowCursor) {
        // Create the pixmap, that will be a mask, that hides the cursor. This pixmap will set as cursor pixmap.
        // XCreatePixmap can generate BadAlloc , BadDrawable , and BadValue errors.
        cursorPixmap = ::XCreatePixmap(m_pXServerConnection->Get(), ::XRootWindow(m_pXServerConnection->Get(), visualInfo->screen), 1, 1, 1);
        // Create the color.
        ::XColor color;
        // Create the cursor with this pixmap and color.
        // XCreatePixmapCursor can generate BadAlloc and BadPixmap errors.
        cursorId = ::XCreatePixmapCursor(m_pXServerConnection->Get(), cursorPixmap, cursorPixmap, &color, &color, 0, 0);
        // Set cursor attributes.
        setWindowAttributes.cursor = cursorId;
        valueMask |= CWCursor;
    }
    // Create window.
    ::Window window;
    if(NULL == pParentWindow) {
        // Border width must be nil for the top-level windows!
        // XCreateWindow can generate BadAlloc BadColor, BadCursor, BadMatch, BadPixmap, BadValue, and BadWindow errors.
        window = ::XCreateWindow(m_pXServerConnection->Get(), ::XRootWindow(m_pXServerConnection->Get(), visualInfo->screen), posX, posY, Rectangle.GetWidth(),
                               Rectangle.GetHeight(), 0, visualInfo->depth, InputOutput, visualInfo->visual, valueMask , &setWindowAttributes);
    } else {
        // XCreateWindow can generate BadAlloc BadColor, BadCursor, BadMatch, BadPixmap, BadValue, and BadWindow errors.
        window = ::XCreateWindow(m_pXServerConnection->Get(), pParentWindow->Get(), posX, posY, Rectangle.GetWidth(), Rectangle.GetHeight(), iBorderWidth, visualInfo->depth,
                               InputOutput, visualInfo->visual, valueMask , &setWindowAttributes);
    }
    // XFreeCursor can generate a BadCursor error.
    ::XFreeCursor(m_pXServerConnection->Get(), cursorId);
    // XFrePixmap can generate a BadPixmap error.
    ::XFreePixmap(m_pXServerConnection->Get(), cursorPixmap);
    ::XFree(visualInfo);
    // Set default window name, if the specified window name is empty.
    char* windowName = NULL;
    const char *wn = "OOXlib Window";
    if(WindowName.empty()) {
        windowName = const_cast<char*>(wn);
    } else {
        windowName = const_cast<char*>(WindowName.c_str());
    }
    // Create properties from character strings.
    ::XTextProperty windowNameProperty, iconNameProperty;
    if(0 == ::XStringListToTextProperty(&windowName, 1, &windowNameProperty) || 0 == ::XStringListToTextProperty(&windowName, 1, &iconNameProperty)) {
        // XDestroyWindow() can generate a BadWindow error.
        ::XDestroyWindow(m_pXServerConnection->Get(), window);
        OOXLib_THROW(CXStringListToTextPropertyException);
    };
    // Create size hints structure.
    // Position has no effect, if the window's parent is a root window.
    ::XSizeHints sizeHints;
    sizeHints.flags         = PPosition | PSize;
    sizeHints.x             = Rectangle.GetPositionX();
    sizeHints.y             = Rectangle.GetPositionY();
    sizeHints.width         = Rectangle.GetWidth();
    sizeHints.height        = Rectangle.GetHeight();
    if(bIsResizeable) {
        if(NULL != pMinSize) {
            sizeHints.flags |= PMinSize;
            sizeHints.min_width     = pMinSize->GetX();
            sizeHints.min_height    = pMinSize->GetY();
        }
        if(NULL != pMaxSize) {
            sizeHints.flags |= PMaxSize;
            sizeHints.max_width     = pMaxSize->GetX();
            sizeHints.max_height    = pMaxSize->GetY();
        }
    } else {
        // Min and max width and height are set to prevent window's resizing. In addition,
        // this hides the 'restore' button on the title bar of the window.
        sizeHints.flags = sizeHints.flags | PMinSize | PMaxSize;;
        sizeHints.min_width     = Rectangle.GetWidth();
        sizeHints.min_height    = Rectangle.GetHeight();
        sizeHints.max_width     = Rectangle.GetWidth();
        sizeHints.max_height    = Rectangle.GetHeight();
    };
    // Create window manager hints.
    ::XWMHints wmHints;
    if(IconPath.empty()) {
        wmHints.flags = StateHint | InputHint;
        wmHints.initial_state = NormalState;
        wmHints.input = True;
    } else {
        m_pIcon = new CIcon(m_pXServerConnection, pScreen, IconPath);
        wmHints.flags = StateHint | IconPixmapHint | IconMaskHint | IconWindowHint | InputHint;
        wmHints.initial_state = NormalState;
        wmHints.input = True;
        wmHints.icon_pixmap = m_pIcon->Get();
        wmHints.icon_mask = m_pIcon->GetMask();
        wmHints.icon_window = window;
    }
    // Create the class hint.
    ::XClassHint classHints;
    char *className = NULL;
    const char *cn = "OOXlibWindow";
    if(ClassName.empty()) {
        className = const_cast<char*>(cn);
    } else {
        className = const_cast<char*>(ClassName.c_str());
    }
    // Class name is used to associate the resources with some class of applications.
    classHints.res_name = NULL;
    classHints.res_class = className;
    // Set properties.
    // XSetWMProperties can generate BadAlloc and BadWindow errors.
    ::XSetWMProperties(m_pXServerConnection->Get(), window, &windowNameProperty, &iconNameProperty, NULL, 0, &sizeHints, &wmHints, &classHints);
    if(NULL == pParentWindow) {
        if(NULL != pEventHandler) {
            // If we have an error handler, we create an atom for the window, whos parent is the root window.
            // It's necessary to allow the program to close itself. Otherwise, the window (and the process) will
            // be killed by the server, and that's not good.
            // XInternAtom can generate BadAlloc and BadValue errors.
            ::Atom atom = ::XInternAtom(m_pXServerConnection->Get(), "WM_DELETE_WINDOW", false);
            // XSetWMProtocols can generate BadAlloc and BadWindow errors.
            // It returns zero - it fails, but we don't need to check, cause when the XSetWMProtocols functon fails,
            // window will be destroyed by the server.
            ::XSetWMProtocols(m_pXServerConnection->Get(), window, &atom, 1);
        }
        // If there is no event handler, we allow the sever to kill the process.
    } else {
        // If the window has a parent, we set to this window the 'transient for hint' property,
        // which will tell the window manager, that this window belongs to the parent window,
        // and must be handled as a part of it. (For example, the 'WM_DELETE_WINDOW' message will be passed to the parent window.)
        // XSetTransientForHint can generate BadAlloc and BadWindow errors.
        ::XSetTransientForHint(m_pXServerConnection->Get(), window, pParentWindow->Get());
    };
    ::XFree(windowNameProperty.value);
    ::XFree(iconNameProperty.value);
    m_Window = window;
    m_pParentWindow = pParentWindow;
    m_Rectangle = Rectangle;
    m_iEventMask = iEventMask;
    m_pEventHandler = pEventHandler;
    m_iId = Register(this);
    // Callback method.
    OnCreate();
}
/**
 * Calls OnDestroy, than hides the window, deletes icon, undefines cursor and finally destroys the window..
 */
void CWindow::Destroy() {
    // Callback method.
    OnDestroy();
    // Unregister windows
    if(NULL == m_pParentWindow) {
        int windowsCount = m_Windows.size();
        if(windowsCount > 0) {
            windowsCount--;
            for(int i = windowsCount; i >= 0; i--) {
                if(NULL != m_Windows[i]) {
                    m_Windows[i]->Unregister(i);
                }
            }
        }
    } else {
        m_pParentWindow->Unregister(m_iId);
    }
    // XUnmapWindow can generate a BadWindow error.
    ::XUnmapWindow(m_pXServerConnection->Get(), m_Window);
    // Flush the output buffer.
    ::XFlush(m_pXServerConnection->Get());
    // Delete icon.
    delete m_pIcon;
    // XUndefineCursor can generate a BadWindow error.
    if(!m_bShowCursor) {
        ::XUndefineCursor(m_pXServerConnection->Get(), m_Window);
    }
    // XDestroyWindow() can generate a BadWindow error.
    ::XDestroyWindow(m_pXServerConnection->Get(), m_Window);
}
/**
 * Hides the window.
 */
void CWindow::Hide() {
    // Callback method.
    OnHide();
    // Unmap window.
    if(NULL == m_pParentWindow) {
        int windowsCount = m_Windows.size();
        if(windowsCount > 0) {
            windowsCount--;
            for(int i = windowsCount; i > static_cast<int>(m_iId); i--) {
                if(NULL != m_Windows[i]) {
                    m_Windows[i]->Hide();
                }
            }
        }
    }
    // XUnmapWindow can generate a BadWindow error.
    ::XUnmapWindow(m_pXServerConnection->Get(), m_Window);
    // Flush the output buffer.
    ::XFlush(m_pXServerConnection->Get());
}
/**
 * Shows the window.
 */
void CWindow::Show() {
    // Select the input events.
    // XSelectInput can generate a BadWindow error.
    ::XSelectInput(m_pXServerConnection->Get(), m_Window, m_iEventMask);
    // Map the window.
    // XMapWindow can generate a BadWindow error.
    ::XMapWindow(m_pXServerConnection->Get(), m_Window);
    // If the window's parent is a root window, move the window to the point, that is contained in m_Rectangle structure.
    if(NULL == m_pParentWindow) {
        // XMoveWindow can generate a BadWindow error.
        ::XMoveWindow(m_pXServerConnection->Get(), m_Window, m_Rectangle.GetPositionX(), m_Rectangle.GetPositionY());
    };
    // Callback method.
    OnShow();
    // Flushes the output buffer.
    ::XFlush(m_pXServerConnection->Get());
    // If this window is the top-level window,
    // show his children and start the event handling cycle.
    if(NULL == m_pParentWindow) {
        int windowsCount = m_Windows.size();
        for(int i = m_iId + 1; i < windowsCount; i++) {
            if(NULL != m_Windows[i]) {
                m_Windows[i]->Show();
            }
        }
        while(HandleEvents()) {}
    }
}
/**
 * Returns the window descriptor.
 * \return Window descriptor
 */
::Window CWindow::Get() const {
    return m_Window;
}
/**
 * Returns the window descriptor.
 * \return Window descriptor
 */
CWindow::operator ::Window() const {
    return m_Window;
}
/**
 * Returns the window rectangle.
 * \return Window rectangle.
 */
CUInt2dRectangle CWindow::GetRectangle() const {
    return m_Rectangle;
}
/**
 * Returns the window position.
 * \return Window position.
 */
CUInt2dPoint CWindow::GetPosition() const {
    return m_Rectangle.GetPosition();
}
/**
 * Returns the window size.
 * \return Window size.
 */
CUInt2dSize CWindow::GetSize() const {
    return m_Rectangle.GetSize();
}
/**
 * Changes the window rectangle.
 * \param Rectangle New window rectangle.
 */
void CWindow::SetRectangle(const CUInt2dRectangle &Rectangle) {
    // XMoveResizeWindow can generate BadValue and BadWindow errors.
    ::XMoveResizeWindow(m_pXServerConnection->Get(), m_Window, Rectangle.GetPositionX(), Rectangle.GetPositionY(), Rectangle.GetWidth(), Rectangle.GetHeight());
}
/**
 * Registers the specified window as a child of the parent window.
 * \param pWindow Window to register.
 * \return Window id.
 */
size_t CWindow::Register(IWindow *pWindow) {
    if(NULL == pWindow) {
        OOXLib_THROW(CNULLPtrIWindowException);
    }
    if(NULL == m_pParentWindow) {
        m_Windows.push_back(pWindow);
        return m_Windows.size() - 1;
    } else {
        return m_pParentWindow->Register(pWindow);
    }
}
/**
 * Unregisters the specified window.
 */
void CWindow::Unregister(const size_t iId) {
    if(NULL == m_pParentWindow) {
        m_Windows[iId] = NULL;
    } else {
        m_pParentWindow->Unregister(iId);
    }
    if(m_iId == iId) {
        m_iId = 0u;
    }
}
/**
 * Handles events
 * \return False if needed to exit. else - true.
 */
bool CWindow::HandleEvents() {
    // Get an event.
    ::XEvent event;
    ::XNextEvent(m_pXServerConnection->Get(), &event);
    // Try to find the window.
    IWindow* window = NULL;
    int windowsCount = m_Windows.size();
    for(int i = 0; i < windowsCount; i++) {
        if(NULL != m_Windows[i]) {
            if(event.xany.window == m_Windows[i]->Get()) {
                window = m_Windows[i];
                break;
            }
        }
    }
    // If not found - return from handler.
    if(NULL == window) {
        return false;
    }
    return window->RunEventHandler(event);
}
/**
 * Calls the event handler.
 * \param Event XEvent structure.
 * \return False if needed to exit, else - true.
 */
bool CWindow::RunEventHandler(::XEvent &Event) {
    if(NULL == m_pEventHandler) {
        return true;
    }
    return m_pEventHandler->HandleEvents(Event, this);
}
/**
 * OnCreate handler.
 */
void CWindow::OnCreate() {}
/**
 * OnDestroy handler.
 */
void CWindow::OnDestroy() {
    // Do not throw outside from this method - it's called from the destructor!
}
/**
 * OnHide handler.
 */
void CWindow::OnHide() {}
/**
 * OnShow handler.
 */
void CWindow::OnShow() {}
/**
 * OnExpose handler.
 */
void CWindow::OnExpose() {}
/**
 * OnGotFocus handler.
 */
void CWindow::OnGotFocus() {}
/**
 * OnLostFocus handler.
 */
void CWindow::OnLostFocus() {}
/**
 * OnKeyPress handler.
 * \param iKey Key id.
 */
void CWindow::OnKeyPress(const ::XID iKey UNUSED_PARAM) {}
/**
 * OnKeyRelease handler.
 * \param iKey Key id.
 */
void CWindow::OnKeyRelease(const ::XID iKey UNUSED_PARAM) {}
/**
 * OnButtonPress handler.
 * \param iButton Button id.
 * \param iX X position of a pointer.
 * \param iY Y position of a pointer.
 */
void CWindow::OnButtonPress(const unsigned int iButton UNUSED_PARAM, const int iX UNUSED_PARAM, const int iY UNUSED_PARAM) {}
/**
 * OnButtonRelease handler.
 * \param iButton Button id.
 * \param iX X position of a pointer.
 * \param iY Y position of a pointer.
 */
void CWindow::OnButtonRelease(const unsigned int iButton UNUSED_PARAM, const int iX UNUSED_PARAM, const int iY UNUSED_PARAM) {}
/**
 * OnMouseEnter handler.
 * \param iX X position of a pointer.
 * \param iY Y position of a pointer.
 */
void CWindow::OnMouseEnter(const int iX UNUSED_PARAM, const int iY UNUSED_PARAM) {}
/**
 * OnMouseExit handler.
 * \param iX X position of a pointer.
 * \param iY Y position of a pointer.
 */
void CWindow::OnMouseExit(const int iX UNUSED_PARAM, const int iY UNUSED_PARAM) {}
/**
 * OnMouseMove handler.
 * \param iX X position of a pointer.
 * \param iY Y position of a pointer.
 */
void CWindow::OnMouseMove(const int iX UNUSED_PARAM, const int iY UNUSED_PARAM) {}

} // OOXlib
